package st.learnopengl.apps.light

import glm_.glm
import glm_.mat4x4.Mat4
import glm_.vec3.Vec3
import gln.BufferTarget
import gln.VertexAttrType
import gln.draw.DrawMode
import gln.draw.glDrawArrays
import gln.glClearColor
import gln.glf.VertexAttribute
import gln.identifiers.GlBuffer
import gln.identifiers.GlProgram
import gln.uniform.glUniform
import gln.vertexArray.GlVertexArray
import st.learnopengl.common.App
import st.learnopengl.common.GLUT
import st.learnopengl.common.Resource
import org.lwjgl.opengl.GL11C

class SpecularLight(width: Int, height: Int, title: String) : App(width, height, title) {

    private var program: GlProgram? = null
    private var vao: GlVertexArray? = null
    private var vbo: GlBuffer? = null

    private var model_location: Int = -1
    private var view_location: Int = -1
    private var project_location: Int = -1
    private var light_pos_location: Int = -1;
    private var object_color_location: Int = -1
    private var world_light_color_location: Int = -1
    private var object_type_location: Int = -1
    private var eye_pos_location: Int = -1

    private lateinit var aPosAttr: VertexAttribute
    private lateinit var aNormAttr: VertexAttribute

    private val lightPos = Vec3(1.2f, 1.5f, -1.5f)
    private val eyePos = Vec3(-1.2f, 3.0f, 3.0f)



    override fun onInit() {
        program = GLUT.createProgram("shaders/light/spec_color_vs.glsl"
            , "shaders/light/spec_color_fs.glsl")

        vao = GlVertexArray.gen()
        vao!!.bound {
            vbo = GlBuffer.gen()
            vbo!!.bound(BufferTarget.ARRAY) {
                data(Resource.cube_vertex_normal)
            }
        }
        light_pos_location = program!!.getUniformLocation("light_pos")
        model_location = program!!.getUniformLocation("model")
        view_location = program!!.getUniformLocation("view")
        project_location = program!!.getUniformLocation("project")
        object_color_location = program!!.getUniformLocation("object_color")
        world_light_color_location = program!!.getUniformLocation("world_light_color")
        object_type_location = program!!.getUniformLocation("object_type")
        eye_pos_location = program!!.getUniformLocation("eye_pos")

        aPosAttr = VertexAttribute(0, 3, VertexAttrType.FLOAT, false, 6 * 4, 0)
        aNormAttr = VertexAttribute(1, 3, VertexAttrType.FLOAT, false, 6 * 4, 3 * 4)

        GL11C.glEnable(GL11C.GL_DEPTH_TEST)
        glClearColor(Vec3(0, 0, 0))
    }

    override fun loop() {
        GL11C.glClear(GL11C.GL_COLOR_BUFFER_BIT or GL11C.GL_DEPTH_BUFFER_BIT)

        val viewMatrix = glm.lookAt(eyePos, Vec3(0, 0, 0), Vec3(0.0f, 1.0f, 0.0f))
        val projectMatrix = glm.perspective(glm.radians(60.0f), 4.0f / 3.0f, 0.001f, 1000.0f)

        program!!.use {


            glUniform(object_color_location, Vec3(1.0f, 0.5f, 0.31f))
            glUniform(world_light_color_location, Vec3(1.0f, 1.0f, 1.0f))
            glUniform(light_pos_location, lightPos)
            glUniform(eye_pos_location, eyePos)

            vao!!.bound {
                vbo!!.bind(BufferTarget.ARRAY)
                aPosAttr.enable()
                aPosAttr.pointer()

                aNormAttr.enable()
                aNormAttr.pointer()

                /**
                 * draw light source first
                 */
                var lightMatrix = Mat4(1.0f)
                lightMatrix = glm.translate(lightMatrix, lightPos)
                lightMatrix = glm.scale(lightMatrix, Vec3(0.2f))

                glUniform(model_location, lightMatrix)
                glUniform(view_location, viewMatrix)
                glUniform(project_location, projectMatrix)

                glUniform(object_type_location, Resource.TYPE.LIGHT_SOURCE.v)

                glDrawArrays(DrawMode.TRIANGLES,36)
            }

            vao!!.bound {
                vbo!!.bind(BufferTarget.ARRAY)
                aPosAttr.enable()
                aPosAttr.pointer()

                aNormAttr.enable()
                aNormAttr.pointer()

                /**
                 * draw light source first
                 */
                var modelMatrix = Mat4(1.0f)

                glUniform(model_location, modelMatrix)
                glUniform(view_location, viewMatrix)
                glUniform(project_location, projectMatrix)

                glUniform(object_type_location, Resource.TYPE.OBJECT.v)

                glDrawArrays(DrawMode.TRIANGLES,36)
            }

        }
    }

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            SpecularLight(1280, 720, "Specular light").run()
        }
    }
}